/***
 * 动态圆效果集合
 */

// 波纹圆
class CircleRippleMaterialProperty {
  _definitionChanged;
  _color;
  _speed;

  color;
  speed;
  count;
  gradient;

  source;

  constructor(color, speed, count, gradient) {
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._speed = undefined;

    this.color = color;
    this.speed = speed;
    this.count = count;
    this.gradient = gradient;

    this.source = `
    uniform vec4 color;
    uniform float speed;
    uniform float count;
    uniform float gradient;

    czm_material czm_getMaterial(czm_materialInput materialInput){
      czm_material material = czm_getDefaultMaterial(materialInput);
      material.diffuse = color.rgb;
      vec2 st = materialInput.st;
      float dis = distance(st, vec2(0.5, 0.5));
      float per = fract(czm_frameNumber * speed / 1000.0);
      if(count == 1.0){
        if(dis > per * 0.5){
          discard;
        }else {
          material.alpha = color.a  * dis / per / 2.0;
        }
      } else {
        vec3 str = materialInput.str;
        if(abs(str.z)  > 0.001){
        discard;
        }
        if(dis > 0.5){
        discard;
        } else {
        float perDis = 0.5 / count;
        float disNum;
        float bl = 0.0;
        for(int i = 0; i <= 999; i++){
            if(float(i) <= count){
              disNum = perDis * float(i) - dis + per / count;
              if(disNum > 0.0){
                if(disNum < perDis){
                  bl = 1.0 - disNum / perDis;
                }
                else if(disNum - perDis < perDis){
                  bl = 1.0 - abs(1.0 - disNum / perDis);
                }
                material.alpha = pow(bl,(1.0 + 10.0 * (1.0 - gradient)));
              }
          }
        }
      }
    }
    return material;
    }`;

    this.addMaterial();
  }

  get isConstant() {
    return false;
  }

  get definitionChanged() {
    return this._definitionChanged;
  }

  getType() {
    return "CircleRippleMaterial";
  }

  getValue(time, result) {
    if (!Cesium.defined(result)) {
      result = {};
    }

    result.color = Cesium.Property.getValueOrDefault(
      this._color,
      time,
      result.color,
      Cesium.Color.WHITE
    );
    result.speed = Cesium.Property.getValueOrDefault(
      this._speed,
      time,
      10,
      result.speed
    );
    result.count = this.count;
    result.gradient = this.gradient;
    return result;
  }

  equals(other) {
    return (
      this === other ||
      (other instanceof CircleRippleMaterialProperty &&
        Cesium.Property.equals(this._color, other._color) &&
        Cesium.Property.equals(this._speed, other._speed) &&
        Cesium.Property.equals(this.count, other.count) &&
        Cesium.Property.equals(this.gradient, other.gradient))
    );
  }

  addMaterial() {
    Cesium.Material._materialCache.addMaterial(this.getType(), {
      fabric: {
        type: this.getType(),
        uniforms: {
          color: Cesium.Color.fromCssColorString(this.color),
          speed: this.speed,
          count: this.count,
          gradient: this.gradient,
        },
        source: this.source,
      },
      translucent: true,
    });
  }
}

export class CircleRipple {
  viewer;
  position;
  id;
  options;

  CircleEntity;

  constructor(viewer, position, id, options) {
    this.viewer = viewer;
    this.position = Cesium.Cartesian3.fromDegrees(position[0], position[1]);
    this.id = id;
    this.options = options;
  }

  init() {
    this.CircleEntity = this.viewer.entities.add({
      position: this.position,
      id: this.id,
      ellipse: {
        semiMinorAxis: this.options.radius,
        semiMajorAxis: this.options.radius,
        material: new CircleRippleMaterialProperty(
          this.options.color,
          this.options.speed,
          this.options.count,
          this.options.gradient
        ),
      },
    });
  }

  remove() {
    this.viewer.entities.remove(this.CircleEntity);
  }
}

// 扩散圆
class CircleDiffuseMaterialProperty {
  _definitionChanged;
  _color;
  _speed;

  color;
  speed;

  source;

  constructor(color, speed) {
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._speed = undefined;
    this.color = color;
    this.speed = speed;

    this.source = `
    uniform vec4 color;
    uniform float speed;

    vec3 circlePing(float r, float innerTail,  float frontierBorder, float timeResetSeconds,  float radarPingSpeed,  float fadeDistance){
      float t = fract(czm_frameNumber * speed / 1000.0);
      float time = mod(t, timeResetSeconds) * radarPingSpeed;
      float circle;
      circle += smoothstep(time - innerTail, time, r) * smoothstep(time + frontierBorder,time, r);
      circle *= smoothstep(fadeDistance, 0.0, r);
      return vec3(circle);
    }

    czm_material czm_getMaterial(czm_materialInput materialInput){
      czm_material material = czm_getDefaultMaterial(materialInput);
      vec2 st = materialInput.st * 2.0  - 1.0 ;
      vec2 center = vec2(0.);
      float time = fract(czm_frameNumber * speed / 1000.0);
      vec3 flagColor;
      float r = length(st - center) / 4.;
      flagColor += circlePing(r, 0.25, 0.025, 4.0, 0.3, 1.0) * color.rgb;
      material.alpha = length(flagColor);
      material.diffuse = flagColor.rgb;
      return material;
    }`;

    this.addMaterial();
  }

  get isConstant() {
    return false;
  }

  get definitionChanged() {
    return this._definitionChanged;
  }

  getType() {
    return "CircleDiffuseMaterial";
  }

  getValue(time, result) {
    if (!Cesium.defined(result)) {
      result = {};
    }

    result.color = Cesium.Property.getValueOrDefault(
      this._color,
      time,
      result.color,
      Cesium.Color.RED
    );
    result.speed = Cesium.Property.getValueOrDefault(
      this._speed,
      time,
      10,
      result.speed
    );
    return result;
  }

  equals(other) {
    return (
      this === other ||
      (other instanceof CircleDiffuseMaterialProperty &&
        Cesium.Property.equals(this._color, other._color) &&
        Cesium.Property.equals(this._speed, other._speed))
    );
  }

  addMaterial() {
    Cesium.Material._materialCache.addMaterial(this.getType(), {
      fabric: {
        type: this.getType(),
        uniforms: {
          color: Cesium.Color.fromCssColorString(this.color),
          speed: this.speed,
        },
        source: this.source,
      },
      translucent: true,
    });
  }
}

export class CircleDiffuse {
  viewer;
  position;
  id;
  options;

  CircleEntity;

  constructor(viewer, position, id, options) {
    this.viewer = viewer;
    this.position = Cesium.Cartesian3.fromDegrees(position[0], position[1]);
    this.id = id;
    this.options = options;
  }

  init() {
    this.CircleEntity = this.viewer.entities.add({
      position: this.position,
      id: this.id,
      ellipse: {
        semiMinorAxis: this.options.radius,
        semiMajorAxis: this.options.radius,
        material: new CircleDiffuseMaterialProperty(
          this.options.color,
          this.options.speed
        ),
      },
    });
  }

  remove() {
    this.viewer.entities.remove(this.CircleEntity);
  }
}

// 螺旋圆
class CircleSpiralMaterialProperty {
  _definitionChanged;
  _color;
  _speed;

  color;
  speed;

  source;

  constructor(color, speed) {
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._speed = undefined;
    this.color = color;
    this.speed = speed;

    this.source = `
    uniform vec4 color;
    uniform float speed;
    #define PI 3.14159265359

    vec2 rotate2D (vec2 _st, float _angle) {
      _st =  mat2(cos(_angle),-sin(_angle),  sin(_angle),cos(_angle)) * _st;
      return _st;
    }
      czm_material czm_getMaterial(czm_materialInput materialInput){
      czm_material material = czm_getDefaultMaterial(materialInput);
      vec2 st = materialInput.st * 2.0 - 1.0;
      st *= 1.6;
      float time = czm_frameNumber * speed / 1000.0;
      float r = length(st);
      float w = .3;
      st = rotate2D(st,(r*PI*6.-time*2.));
      float a = smoothstep(-w,.2,st.x) * smoothstep(w,.2,st.x);
      float b = abs(1./(sin(pow(r,2.)*2.-time*1.3)*6.))*.4;
      material.alpha = a * b ;
      material.diffuse = color.rgb * a * b  * 3.0;
      return material;
    }`;

    this.addMaterial();
  }

  get isConstant() {
    return false;
  }

  get definitionChanged() {
    return this._definitionChanged;
  }

  getType() {
    return "CircleSpiralMaterial";
  }

  getValue(time, result) {
    if (!Cesium.defined(result)) {
      result = {};
    }

    result.color = Cesium.Property.getValueOrDefault(
      this._color,
      time,
      result.color,
      Cesium.Color.RED
    );
    result.speed = Cesium.Property.getValueOrDefault(
      this._speed,
      time,
      10,
      result.speed
    );
    return result;
  }

  equals(other) {
    return (
      this === other ||
      (other instanceof CircleDiffuseMaterialProperty &&
        Cesium.Property.equals(this._color, other._color) &&
        Cesium.Property.equals(this._speed, other._speed))
    );
  }

  addMaterial() {
    Cesium.Material._materialCache.addMaterial(this.getType(), {
      fabric: {
        type: this.getType(),
        uniforms: {
          color: Cesium.Color.fromCssColorString(this.color),
          speed: this.speed,
        },
        source: this.source,
      },
      translucent: true,
    });
  }
}

export class CircleSpiral {
  viewer;
  position;
  id;
  options;

  CircleEntity;

  constructor(viewer, position, id, options) {
    this.viewer = viewer;
    this.position = Cesium.Cartesian3.fromDegrees(position[0], position[1]);
    this.id = id;
    this.options = options;
  }

  init() {
    this.CircleEntity = this.viewer.entities.add({
      position: this.position,
      id: this.id,
      ellipse: {
        semiMinorAxis: this.options.radius,
        semiMajorAxis: this.options.radius,
        material: new CircleSpiralMaterialProperty(
          this.options.color,
          this.options.speed
        ),
      },
    });
  }

  remove() {
    this.viewer.entities.remove(this.CircleEntity);
  }
}

// 光线扩散
class CircleLineScanMaterialProperty {
  _definitionChanged;
  _color;
  _speed;

  color;
  speed;
  time;

  source;

  constructor(color, speed, time) {
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._speed = undefined;
    this.color = color;
    this.speed = speed;
    this.time = time;

    this.source = `
    uniform vec4 color;
    uniform float speed;
    float circle(vec2 uv, float r, float blur) {
      float d = length(uv) * 1.0; /* 2.0 */
      float c = smoothstep(r+blur, r, d);
      return c;
    }
    czm_material czm_getMaterial(czm_materialInput materialInput)
    {
      czm_material material = czm_getDefaultMaterial(materialInput);
      vec2 st = materialInput.st - 0.5;
      material.emission = vec3(0);
      float t = fract(czm_frameNumber * (11000.0 - speed) / 500000.0);
      float s = 0.3;
      float radius1 = smoothstep(.0, s, t) * 0.5;
      float alpha1 = circle(st, radius1, 0.01) * circle(st, radius1, -0.01);
      float alpha2 = circle(st, radius1, 0.01 - radius1) * circle(st, radius1, 0.01);
      float radius2 = 0.5 + smoothstep(s, 1.0, t) * 0.5;
      float alpha3 = circle(st, radius1, radius2 + 0.01 - radius1) * circle(st, radius1, -0.01);
      material.alpha = smoothstep(1.0, s, t) * (alpha1 + alpha2*0.1 + alpha3*0.1);
      material.alpha *= color.a ;
      material.diffuse = 2.8 * color.rgb;
      return material;
    }`;

    this.addMaterial();
  }

  get isConstant() {
    return false;
  }

  get definitionChanged() {
    return this._definitionChanged;
  }

  getType() {
    return "CircleLineScanMaterial";
  }

  getValue(time, result) {
    if (!Cesium.defined(result)) {
      result = {};
    }

    result.color = Cesium.Property.getValueOrDefault(
      this._color,
      time,
      result.color,
      Cesium.Color.RED
    );
    result.speed = Cesium.Property.getValueOrDefault(
      this._speed,
      time,
      10,
      result.speed
    );
    return result;
  }

  equals(other) {
    return (
      this === other ||
      (other instanceof CircleLineScanMaterialProperty &&
        this.Cesium.Property.equals(this._color, other._color) &&
        this.Cesium.Property.equals(this._speed, other._speed))
    );
  }

  addMaterial() {
    Cesium.Material._materialCache.addMaterial(this.getType(), {
      fabric: {
        type: this.getType(),
        uniforms: {
          color: Cesium.Color.fromCssColorString(this.color),
          speed: this.speed,
        },
        source: this.source,
      },
      translucent: true,
    });
  }
}

export class CircleLineScan {
  viewer;
  position;
  id;
  options;

  CircleEntity;

  constructor(viewer, position, id, options) {
    this.viewer = viewer;
    this.position = Cesium.Cartesian3.fromDegrees(position[0], position[1]);
    this.id = id;
    this.options = options;
  }

  init() {
    this.CircleEntity = this.viewer.entities.add({
      position: this.position,
      id: this.id,
      ellipse: {
        semiMinorAxis: this.options.radius,
        semiMajorAxis: this.options.radius,
        material: new CircleLineScanMaterialProperty(
          this.options.color,
          this.options.speed,
          this.options.time
        ),
      },
    });
  }

  remove() {
    this.viewer.entities.remove(this.CircleEntity);
  }
}

// 刻度圆
// class CircleDegreeMaterialProperty {
//   _definitionChanged;
//   _color;
//   _speed;

//   color;
//   speed;
//   count;
//   gradient;

//   source;

//   constructor(color, speed, count, gradient) {
//     this._definitionChanged = new Cesium.Event();
//     this._color = undefined;
//     this._speed = undefined;

//     this.color = color;
//     this.speed = speed;
//     this.count = count;
//     this.gradient = gradient;

//     this.source = `
//     uniform vec4 color;
//     uniform float speed;
//     uniform float count;
//     uniform float gradient;

//     czm_material czm_getMaterial(czm_materialInput materialInput){
//       czm_material material = czm_getDefaultMaterial(materialInput);
//       material.diffuse = 1.5 * color.rgb;
//       vec2 st = materialInput.st;
//       float dis = distance(st, vec2(0.5, 0.5));
//       float per = fract(czm_frameNumber * speed / 1000.0);
//       material.alpha = color.a  * dis / 2.0;
//       if(dis > per * 0.5) {
//         material.alpha = 0.0;
//       }

//       return material;
//     }`;

//     this.addMaterial();
//   }

//   get isConstant() {
//     return false;
//   }

//   get definitionChanged() {
//     return this._definitionChanged;
//   }

//   getType() {
//     return "CircleDegreeMaterial";
//   }

//   getValue(time, result) {
//     if (!Cesium.defined(result)) {
//       result = {};
//     }

//     result.color = Cesium.Property.getValueOrDefault(
//       this._color,
//       time,
//       result.color,
//       Cesium.Color.RED
//     );
//     result.speed = Cesium.Property.getValueOrDefault(
//       this._speed,
//       time,
//       10,
//       result.speed
//     );
//     result.count = this.count;
//     result.gradient = this.gradient;
//     return result;
//   }

//   equals(other) {
//     return (
//       this === other ||
//       (other instanceof CircleDegreeMaterialProperty &&
//         Cesium.Property.equals(this._color, other._color) &&
//         Cesium.Property.equals(this._speed, other._speed) &&
//         Cesium.Property.equals(this.count, other.count) &&
//         Cesium.Property.equals(this.gradient, other.gradient))
//     );
//   }

//   addMaterial() {
//     Cesium.Material._materialCache.addMaterial(this.getType(), {
//       fabric: {
//         type: this.getType(),
//         uniforms: {
//           color: Cesium.Color.fromCssColorString(this.color),
//           speed: this.speed,
//           count: this.count,
//           gradient: this.gradient,
//         },
//         source: this.source,
//       },
//       translucent: true,
//     });
//   }
// }

// export class CircleDegree {
//   viewer;
//   position;
//   id;
//   options;
//   rotation;

//   CircleEntity;

//   constructor(viewer, position, id, options) {
//     this.viewer = viewer;
//     this.position = Cesium.Cartesian3.fromDegrees(position[0], position[1]);
//     this.id = id;
//     this.options = options;
//     this.rotation = Cesium.Math.toRadians(30);
//   }

//   getRotationValue() {
//     this.rotation += -0.03;
//     return this.rotation;
//   }

//   init() {
//     const self = this;
//     this.CircleEntity = this.viewer.entities.add({
//       position: this.position,
//       id: this.id,
//       ellipse: {
//         semiMinorAxis: this.options.radius,
//         semiMajorAxis: this.options.radius,
//         outline: true,
//         outlineColor: Cesium.Color.RED,
//         outlineWidth: 135.0,
//         fill: true,
//         stRotation: new Cesium.CallbackProperty(function getRotationValue() {
//           self.rotation += -0.01;
//           return self.rotation;
//         }, false),
//         material: new Cesium.ImageMaterialProperty({
//           image: "./static/material/circle.png",
//           color: Cesium.Color.RED,
//           transparent: true,
//         }),
//       },
//     });
//   }

//   remove() {
//     this.viewer.entities.remove(this.CircleEntity);
//   }
// }
